/*******************************************************************************
 * FilePath    : /Software/Examples_MG223/BLE/MG223.c
 * Version     : 1.0
 * Brief       :
 * Author      : AndrewHu
 * Company     : Shanghai MacroGiga Electronics CO.,Ltd
 * Email       : Hubinbo@macrogiga.com
 * Date        : 2021-04-13 17:17:26
 * LastEditors : AndrewHu
 * LastEditTime: 2023-03-03 14:39:57
 * Description :
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "Includes.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define LEN_BLE_ADDR 6
u8 POWER_SAVE_OPT = POWER_SAVE_STANDBY;

/* Private variables ---------------------------------------------------------*/
// 芯片内部信息保存，非必要数据
u8 ble_ver = 0x00;
u8 txgain_r = 0x00;
u8 txgain_w = 0x00;
u8 ble_Addr[6] = {0x00};

// BLE ADV_data, maxlen=31
#define LEN_DATA 31
u8 adv_data[LEN_DATA] = {
    // struoture 1
    0x02,                  // 长度
    BLE_GAP_AD_TYPE_FLAGS, // 数据类型
    0x04,                  // 数据

    // struoture 2
    0x11,                                                                                           // 长度
    BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,                                                   // 数据类型
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, // 数据

    // struoture 3
    0x09,                                  // 长度
    BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME,      // 数据类型
    'M', 'G', '2', '2', '3', '-', 'D', 'M' // 数据"MG127-Demo"
};

/* Private function prototypes -----------------------------------------------*/
/*******************************************************************************
 * Function    : BLE_RESET
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2021-04-14 15:00:17
 * Description :
 ******************************************************************************/
void BLE_RESET(void)
{
    GPIO_ResetBits(BLE_nRST_PORT, BLE_nRST);
    Delay_ms(2);
    GPIO_SetBits(BLE_nRST_PORT, BLE_nRST);
    Delay_ms(20);
#if (COMM_OPT_SEL == COMM_I2C_SIMU_NOPU)
    GPIO_Init(BLE_SCL_PORT, BLE_SCL, GPIO_Mode_Out_PP_High_Slow);
#endif
}
/*******************************************************************************
 * Function    : BLE_TX_Power
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2021-04-14 15:00:17
 * Description :
 ******************************************************************************/
void BLE_TX_Power(u8 val)
{
    u8 data_buf[2];

    // set BLE TX Power
    data_buf[0] = 0x08;
    data_buf[1] = val; // BLE_TX_POWER; //0~1F
    MG_Write_Buffer(PA_CFG, data_buf, 2);
}

void BLE_Adv_Auto_Interv(u32 rc_cnt)
{
    u8 data_buf[4];
    u32 cnt_interv = rc_cnt;

    data_buf[0] = cnt_interv & 0xff;
    data_buf[1] = (cnt_interv >> 8) & 0xff;
    data_buf[2] = (cnt_interv >> 16) & 0xff;
    data_buf[3] = 1; // RC_LOAD;
    MG_Write_Buffer(ADV_INTERV_RC_CFG, data_buf, 4);
}

void BLE_Mode_PwrUp(void)
{
    if (POWER_SAVE_OPT == POWER_SAVE_SLEEP)
        MG_Write_Reg(0x3e, 0x01); // rcosc_pd=0, exit from sleep
}

void BLE_Mode_Sleep(void)
{
    MG_Write_Reg(BASEBAND_CFG, 6); // SLP_XO=4, STOP=2，停止广播

    MG_Write_Reg(XO_PD_EN, 0x00);
    MG_Write_Reg(XO_PD_EN, 0x01); // xo_pd=1

    MG_Write_Reg(0x3e, 0x5); // rcosc_pd=1, dpll_pd=1
}

void BLE_Mode_LowV(void) // now only SPI can use this option
{
    // MG_Read_Reg(0xB7); //120ms dectect
    MG_Read_Reg(0x90); // low voltage level
    MG_Read_Reg(0xAD); // low voltage enable

    BLE_SCK_SET();
}

void BLE_Mode_Stdby(void) // standby(deepsleep)
{
    MG_Write_Reg(BASEBAND_CFG, 6); // 停止广播

    MG_Write_Reg(XO_PD_EN, 0x00);
    MG_Write_Reg(XO_PD_EN, 0x01); // xo_pd=1

    MG_Write_Reg(0x23, 0x40);
    // O: irq = H, miso = L
    // I: csn/sck/mosi PU
}

#if 1
unsigned char Patch_Data5_V4x[2] = {0xa0, 0x20};
unsigned char Patch_Data6_V4x[2] = {0x03, 0x02};
unsigned char Patch_Data7_V4x[4] = {0x40, 0x08, 0x03, 0x55};

unsigned char Patch_Data0_V41[4] = {0xc0, 0x0e, 0x03, 0x55};
unsigned char Patch_Data1_V41[4] = {0xc1, 0x44, 0x03, 0x55};

unsigned char Patch_Data2_V41[4] = {0xc4, 0xe0, 0x03, 0x55};
unsigned char Patch_Data3_V41[4] = {0xb0, 0xff, 0x03, 0x55};
unsigned char Patch_Data4_V41[4] = {0xb1, 0x14, 0x03, 0x55};

unsigned char Patch_Data0_V43[4] = {0x25, 0xf4, 0x33, 0x55};
unsigned char Patch_Data1_V43[4] = {0xb1, 0x14, 0x33, 0x55};
unsigned char Patch_Data2_V43[4] = {0xc0, 0x0c, 0x33, 0x55};
unsigned char Patch_Data3_V43[4] = {0xc1, 0x73, 0x33, 0x55};
unsigned char Patch_Data4_V43[4] = {0xc4, 0xe4, 0x33, 0x55};
unsigned char Patch_Data5_V43[4] = {0xc5, 0x2c, 0x33, 0x55};
unsigned char Patch_Data6_V43[4] = {0xc7, 0x60, 0x33, 0x55};
unsigned char Patch_Data7_V43[4] = {0xb0, 0xb0, 0x33, 0x55};

unsigned char power_Data[4] = {0x34, 0x3c, 0x33, 0x55};
#endif
// extern u8 keyData;
void patch(unsigned char ver)
{
    u8 status = 0;
    u8 data_buf[4] = {0x31, 0x08, 0x08, 0x08};

#if (COMM_OPT_SEL == COMM_SPI)
    MG_Write_Buffer(0x3B, data_buf, 4); // csn,sck,miso input no pull
#endif

    MG_Write_Buffer(BG_CAL, Patch_Data5_V4x, 2);
    MG_Write_Buffer(XO_SET, Patch_Data6_V4x, 2);
    MG_Write_Buffer(ABUS_ACC, Patch_Data7_V4x, 4);
#if (BLE_TX_POWER == BLE_TX_POWER6dbm)
    MG_Write_Buffer(ABUS_ACC, power_Data, 4);
#endif

    if (0x42 < ver)
    {
        MG_Write_Buffer(ABUS_ACC, Patch_Data0_V43, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data1_V43, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data2_V43, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data3_V43, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data4_V43, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data5_V43, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data6_V43, 4);

        MG_Read_Buffer(BG_CAL, data_buf, 4);
        // if (data_buf[3] & 0x20)
        if (ValBit(data_buf[3], 5))
        {
            Patch_Data7_V43[1] = ((data_buf[3] & 0x1f) << 2) | 0x80;
        }
        MG_Write_Buffer(ABUS_ACC, Patch_Data7_V43, 4);
    }
    else if (0x41 == ver)
    {
        MG_Write_Buffer(ABUS_ACC, Patch_Data0_V41, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data1_V41, 4);
        MG_Write_Buffer(ABUS_ACC, Patch_Data2_V41, 4);

        MG_Read_Buffer(BG_CAL, data_buf, 4);
        // if (data_buf[3] & 0x20)
        if (ValBit(data_buf[3], 5))
        {
            Patch_Data3_V41[1] = ((data_buf[3] & 0x1f) << 2) | 0x83;
        }
        MG_Write_Buffer(ABUS_ACC, Patch_Data3_V41, 4);

        // 2022/12/2
        MG_Write_Reg(0xca, 0x5c); // efuse
        MG_Write_Reg(0x45, 0x00); // pd_dvdd=0
        MG_Write_Reg(0x42, 0x80); // rden=1
        MG_Write_Reg(0x43, 0x04); // byte4

        data_buf[0] = 0x80; // GenAENpulse
        data_buf[1] = 0x00;
        MG_Write_Buffer(0x41, data_buf, 2);

        status = MG_Read_Reg(0x04);

        MG_Write_Reg(0x42, 0x00); // rden
        MG_Write_Reg(0x45, 0x80); // pd_dvdd
        MG_Write_Reg(0xca, 0x51); // reg
        if (ValBit(status, 6))    // check new202212 flag
        {
            Patch_Data4_V41[1] = 0x18;
        }
        // end 2022/12/2

        MG_Write_Buffer(ABUS_ACC, Patch_Data4_V41, 4);
    }
}
/*******************************************************************************
 * Function   :     	BLE_Init
 * Parameter  :     	{u8} debug
 * Returns    :     	void
 * Description:      power on .BLE must initnal reg .
 * Note:      :
 *******************************************************************************/
void BLE_Init(u8 TxPower, u8 debug)
{
    u8 status = 0;
    u8 data_buf[5];

    MG_Write_Reg(0x3e, 0x01); // rcosc_pd=0
    do
    {
#if (COMM_OPT_SEL == COMM_SPI)
        MG_Write_Reg(CONT_TEST_MODE, 8); // 3 line spi. No use for I2C
#endif
        status = MG_Read_Reg(CHIP_READY);
    } while ((status == 0xFF) || (status & 0x4) != 0x04);

    MG_Write_Reg(RESET_BB, 0x1); // clear flag
    MG_Write_Reg(RESET_BB, 0x0);

    MG_Write_Reg(RESET_BB, 0xDC); // reset bb
    do
    {
        status = MG_Read_Reg(RESET_BB);
    } while ((status & 0x2) != 0x02); // reset done
    MG_Write_Reg(RESET_BB, 0x1);      // clear flag
    MG_Write_Reg(RESET_BB, 0x0);

    MG_Write_Reg(XO_PD_EN, 0x1); // 3//rc32k_sel, xo_pd_en
#if 1
    data_buf[4] = 0x30; // xo_pd_wait_adjust
    data_buf[3] = 0x1e;
    data_buf[2] = 0x29;
    data_buf[1] = 0x05;
    data_buf[0] = 0xdb;
    MG_Write_Buffer(XO_WAIT, data_buf, 5);
#endif

    // apply patch
    status = MG_Read_Reg(IC_VER);
    ble_ver = status;
    patch(status);

    if (debug != 0)
    {
        Printf_NewLine();
        Uart_Send_String("Device: MG223", 13);
        Printf_NewLine();
        Uart_Send_String("chip version: ", 14);
        Uart_Send_Byte2Ascii(status);
    }

    MG_Read_Buffer(0x16, ble_Addr, 6);

    ble_Addr[5]=0x48;
    MG_Write_Buffer(0x16, ble_Addr, 6);//自定义MAC地址

    if (debug != 0)
    {
        Printf_NewLine();
        Uart_Send_String("BleAddr: ", 9);
        Uart_Send_Byte2Ascii(ble_Addr[5]);
        Uart_Send_Byte2Ascii(ble_Addr[4]);
        Uart_Send_Byte2Ascii(ble_Addr[3]);
        Uart_Send_Byte2Ascii(ble_Addr[2]);
        Uart_Send_Byte2Ascii(ble_Addr[1]);
        Uart_Send_Byte2Ascii(ble_Addr[0]);
        Printf_NewLine();
    }

#if 0 // dcdc
    data_buf[0] = MG_Read_Reg(PA_CFG);
    if (!ValBit(data_buf[0], 0)) // DcDc on
    {
        data_buf[4] = 0x03; // buck_dly_set
        data_buf[3] = 0x90; // buck_dly_set
        data_buf[2] = 0xb0;
        data_buf[1] = 0x30;
        data_buf[0] = 0xe0;
        MG_Write_Buffer(0x17, data_buf, 5);
    }
#endif

    //    BLE_TX_Power(BLE_TX_POWER);
    // set BLE TX Power
    data_buf[0] = 0x08;
    data_buf[1] = TxPower; // max 1F
    MG_Write_Buffer(PA_CFG, data_buf, 2);

    MG_Write_Reg(CONFIG, 0x87);   // PREAMBLE_LEN_AUTO | SCRAMBLE_ON | CRC_EN | POWER_UP
    MG_Write_Reg(INT_MASK, 0x6F); // sleep int
}
/*******************************************************************************
 * Function    : BLE_upDte
 * Brief       : 更新广播数据
 * param        {*}
 * return       {*}
 * Description :
 * Date        : 2021-06-03 11:24:52
 ******************************************************************************/
void BLE_upDte(void)
{
    MG_Write_Reg(BASEBAND_CFG, 6); // SLP_XO=4, STOP=2，停止广播
    adv_data[5]++;                 // 更新数据
    BLE_TX();                      // 使能发射
}
/*******************************************************************************
 * Function   :     	BLE_TX
 * Parameter  :     	none
 * Returns    :     	void
 * Description:      Beacon data .process .
 * Note:      :
 *******************************************************************************/
extern u32 adv_interv;
void BLE_TX()
{
    u8 data_buf[3];

    BLE_Mode_PwrUp();

    BLE_Adv_Auto_Interv(adv_interv);

    // BLT FIFO write adv_data . max len:31 byte
    MG_Write_Buffer(W_TX_PAYLOAD, adv_data, LEN_DATA);

    // PDU TYPE: 2  non-connectable undirected advertising . tx add:random address
    // set BLT PDU length:adv_data+6 mac adress.
    data_buf[0] = 0x08;
    data_buf[1] = ADV_NONCONN_IND | ADV_TXADD_RANDOM;
    data_buf[2] = LEN_DATA + LEN_BLE_ADDR;
    MG_Write_Buffer(ADV_PKT_CFG, data_buf, 3);

    MG_Write_Reg(BASEBAND_CFG, 5); // SLP_XO=4, STOP=2, WKUP_EN=1
    MG_Write_Reg(WAKEUP_NOW, 1);

#if (COMM_OPT_SEL == COMM_I2C_SIMU_NOPU)
    GPIO_Init(BLE_SCL_PORT, BLE_SCL, GPIO_Mode_Out_OD_HiZ_Slow);
    GPIO_Init(BLE_SDA_PORT, BLE_SDA, GPIO_Mode_Out_OD_HiZ_Slow);
#endif
}
